#pragma once

#include <iostream>
#include <stdarg.h>
#include <iostream>
#include <string>
#include <cstdarg>
#include <ctime>
#include <unistd.h>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#define Size 1024

enum
{
    Debug = 0,
    Info,
    Warning,
    Error,
    Fatal,
};

enum
{
    Screen = 10,
    OneFile,
    ClassFile
};

std::string LevelToString(int level)
{
    switch (level)
    {
    case Debug:
        return "Debug";
    case Info:
        return "Info";
    case Warning:
        return "Warning";
    case Error:
        return "Error";
    case Fatal:
        return "Fatal";
    default:
        return "Unknown";
    }
}

const int defaultstyle = Screen;
const std::string default_filename = "log.";
const std::string logdir = "log";

class Log
{
private:
    int Style; // 日志输出
    std::string filename;

public:
    Log() : Style(defaultstyle), filename(default_filename)
    {
        //创建默认的日志存放路径
        mkdir(logdir.c_str(),0775);
    }
    ~Log() {}

    void Enable(int Style)
    {
        this->Style = Style;
    }

    std::string TimeStampExlocalTime()   //获取时间
    {
        time_t currtime = time(nullptr);
        struct tm *curr = localtime(&currtime); // localtime
        char time_buffer[128];
        snprintf(time_buffer, sizeof time_buffer, "%d-%d-%d %d:%d:%d",
                 curr->tm_year + 1900, curr->tm_mon + 1, curr->tm_mday, curr->tm_hour, curr->tm_min, curr->tm_sec);
        return time_buffer;
    }

    //写一个日志文件
    void WriteLogOneFile(const std::string &logname, const std::string &loginfo)
    {
        umask(0);
        int fd = open(logname.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0666);
        if (fd < 0)
            return;

        write(fd, loginfo.c_str(), loginfo.size());
        close(fd);

        // std::ofstream out(logname);
        // if(!out.is_open())
        // return;
        // out.write(loginfo.c_str(),loginfo.size());
        // out.close();
    }

    //写一组日志文件
    void WriteLogToClassFile(const std::string &levelstr, const std::string &loginfo)
    {
        //将日志放在指定路径下
        // logdir 默认路径 "log"
        std::string logname = logdir + '/' + filename + levelstr;
        WriteLogOneFile(logname, loginfo);
    }

    //以一定的形式写文件
    void WriteLog(const std::string &levelstr, const std::string &loginfo)
    {
        switch (Style)
        {
        case Screen:
            std::cout << loginfo;
            break;
        case OneFile:
            WriteLogToClassFile("all", loginfo);
            break;
        case ClassFile:
            WriteLogToClassFile(levelstr, loginfo);
            break;
        default:
            break;
        }
    }

    // 集成日志信息
    void LogMessage(int level, const char *format, ...)
    {
        std::string levelstr = LevelToString(level);   // 消息等级
        std::string currtime = TimeStampExlocalTime(); // 时间
        std::string idstr = std::to_string(getpid());  // 进程ID

        char rightbuffer[Size];
        va_list args;
        va_start(args, format);
        vsnprintf(rightbuffer, sizeof rightbuffer, format, args); // format 用户定义的格式进行初始化
        va_end(args);

        char leftbuffer[Size];
        snprintf(leftbuffer, sizeof leftbuffer, "[%s][%s][%s]",
                 levelstr.c_str(), currtime.c_str(), idstr.c_str());

        std::string loginfo = leftbuffer;
        loginfo += rightbuffer;
        WriteLog(levelstr, loginfo);

        // std::cout<<leftbuffer<<std::endl;

        // uint64_t currtime = time(nullptr);
        //  std::string currtime = TimeStampExlocalTime();
        //  printf("[%s][%s]%s\n", LevelToString(level).c_str(),
        //  currtime.c_str(),content);
        /* printf("[%s][%s]%s\n", LevelToString(level).c_str(),
        std::to_string(currtime).c_str(),content); */
    }
};

Log lg;

class Conf
{
    public:
    Conf()
    {
        lg.Enable(Screen);  //调整日志打印位置
    }
    ~Conf()
    {}
};

Conf conf;